//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package org_dao

import (
	"context"

	"atomgit.com/openlinksaas-org/api-server/dao/db_ns"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/org_okr_api"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

type OkrItemInfoDbItem struct {
	Objective     string   `bson:"objective"`
	KeyResultList []string `bson:"keyResultList"`
}

type OkrInfoDbItem struct {
	OkrId        string              `bson:"_id"`
	OrgId        string              `bson:"orgId"`
	MemberUserId string              `bson:"memberUserId"`
	OkrItemList  []OkrItemInfoDbItem `bson:"okrItemList"`
	StartTime    int64               `bson:"startTime"`
	EndTime      int64               `bson:"endTime"`
	CreateTime   int64               `bson:"createTime"`
	UpdateTime   int64               `bson:"updateTime"`
}

func (item *OkrInfoDbItem) ToOkrInfo() *org_okr_api.OkrInfo {
	okrItemList := []*org_okr_api.OkrItemInfo{}
	for _, okrItem := range item.OkrItemList {
		okrItemList = append(okrItemList, &org_okr_api.OkrItemInfo{
			Objective:     okrItem.Objective,
			KeyResultList: okrItem.KeyResultList,
		})
	}
	return &org_okr_api.OkrInfo{
		OkrId:        item.OkrId,
		OrgId:        item.OrgId,
		MemberUserId: item.MemberUserId,
		OkrItemList:  okrItemList,
		StartTime:    item.StartTime,
		EndTime:      item.EndTime,
		CreateTime:   item.CreateTime,
		UpdateTime:   item.UpdateTime,
	}
}

type _OkrDao struct {
	mc *mongo.Collection
}

func newOkrDao(db *mongo.Database) (*_OkrDao, error) {
	mc := db.Collection(db_ns.DB_NS_ORG + "okr")
	_, err := mc.Indexes().CreateOne(context.Background(), mongo.IndexModel{
		Keys: bson.D{{"orgId", 1}, {"memberUserId", 1}, {"startTime", 1}},
	})
	if err != nil {
		return nil, err
	}
	return &_OkrDao{mc: mc}, nil
}

func (db *_OkrDao) Insert(ctx context.Context, dbItem *OkrInfoDbItem) error {
	_, err := db.mc.InsertOne(ctx, dbItem)
	return err
}

func (db *_OkrDao) Exist(ctx context.Context, orgId, memberUserId, okrId string) (bool, error) {
	count, err := db.mc.CountDocuments(ctx, bson.M{"orgId": orgId, "memberUserId": memberUserId, "_id": okrId})
	return count > 0, err
}

func (db *_OkrDao) Get(ctx context.Context, orgId, memberUserId, okrId string) (*OkrInfoDbItem, error) {
	retItem := &OkrInfoDbItem{}
	err := db.mc.FindOne(ctx, bson.M{"orgId": orgId, "memberUserId": memberUserId, "_id": okrId}).Decode(retItem)
	return retItem, err
}

func (db *_OkrDao) Remove(ctx context.Context, orgId, memberUserId, okrId string) error {
	_, err := db.mc.DeleteOne(ctx, bson.M{"orgId": orgId, "memberUserId": memberUserId, "_id": okrId})
	return err
}

func (db *_OkrDao) RemoveByOrg(ctx context.Context, orgId string) error {
	_, err := db.mc.DeleteMany(ctx, bson.M{"orgId": orgId})
	return err
}

func (db *_OkrDao) Count(ctx context.Context, orgId, memberUserId string) (uint32, error) {
	count, err := db.mc.CountDocuments(ctx, bson.M{"orgId": orgId, "memberUserId": memberUserId})
	return uint32(count), err
}

func (db *_OkrDao) List(ctx context.Context, orgId, memberUserId string, offset, limit int64) ([]*OkrInfoDbItem, error) {
	cursor, err := db.mc.Find(ctx, bson.M{"orgId": orgId, "memberUserId": memberUserId}, options.Find().SetSkip(offset).SetLimit(limit).SetSort(bson.M{"startTime": -1}))
	if err != nil {
		return nil, err
	}

	retList := []*OkrInfoDbItem{}
	err = cursor.All(ctx, &retList)
	return retList, err
}

func (db *_OkrDao) Update(ctx context.Context, orgId, memberUserId, okrId string, okrItemList []OkrItemInfoDbItem, startTime, endTime, updateTime int64) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"orgId": orgId, "memberUserId": memberUserId, "_id": okrId},
		bson.M{"$set": bson.M{"okrItemList": okrItemList, "startTime": startTime, "endTime": endTime, "updateTime": updateTime}})
	return err
}
